home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / B-C / CArrangeList 1.01ß.sit / CArrangeList.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-15  |  12.5 KB  |  550 lines  |  [TEXT/KAHL]

  1. #include "CArrangeList.h"
  2.  
  3. void    QuickSort(CArrangeList *theList,short left,short right);
  4. short    CompareItems(Ptr aPtr,Ptr bPtr,short aLen,short bLen);
  5. void    DoubleClick(CArrangeList *theList);
  6.  
  7. extern CursHandle    gHandCursor;
  8.  
  9. void    CArrangeList::IArrangeList(CView *theEnclosure,
  10.     CBureaucrat *theSupervisor,short theWidth,short theHeight,
  11.     short theHEncl,short theVEncl,Boolean hasHoriz,Boolean hasVert,
  12.     Boolean hasSizeBox,short theRows,short theRowWidth,short theRowHeight,
  13.     ShortFunc theCompareProc,VoidFunc theDoubleProc)
  14. {
  15.     register short    i;
  16.     Rect            theRect;
  17.     
  18.     itsSupervisor = theSupervisor;
  19.     itsScrollPane = new(CScrollPane);
  20.     itsScrollPane->IScrollPane(theEnclosure,this,theWidth,theHeight,
  21.         theHEncl,theVEncl,sizFIXEDSTICKY,sizFIXEDSTICKY,hasHoriz,hasVert,
  22.         hasSizeBox);
  23.     
  24.     if (hasVert)
  25.         theWidth -= 15;
  26.     if (hasHoriz)
  27.         theHeight -= 15;
  28.     itsPanorama = new(CListPanorama);
  29.     itsPanorama->IPanorama(itsScrollPane,this,theWidth-2,theHeight-2,
  30.         1,1,sizFIXEDLEFT,sizFIXEDTOP);
  31.     itsPanorama->wantsClicks = true;
  32.     itsPanorama->SetScales(theRowWidth,theRowHeight);
  33.     SetRect(&theRect,0,0,1,theRows);
  34.     itsPanorama->SetBounds(&theRect);
  35.     itsScrollPane->InstallPanorama(itsPanorama);
  36.     
  37.     hIndent = 3;
  38.     vIndent = 4;
  39.     currentSelection = 1;
  40.     
  41.     rows = theRows;
  42.     rowWidth = theRowWidth;
  43.     rowHeight = theRowHeight;
  44.  
  45.     itsOrder = (LongHandle)NewHandleClear((long)(rows * 4));
  46.     for (i = 0; i < rows; i ++)
  47.         (*itsOrder)[i] = i;
  48.     itsItems = NewHandleClear(1L);
  49.     itemOffsets = (LongHandle)NewHandleClear((long)((rows + 1) * 4));
  50.     dirty = true;
  51.     clickTime = 0L;
  52.     clickRow = 0;
  53.     if (!theCompareProc)
  54.         compareProc = CompareItems;
  55.     else
  56.         compareProc = theCompareProc;
  57.     
  58.     if (!theDoubleProc)
  59.         doubleProc = DoubleClick;
  60.     else
  61.         doubleProc = theDoubleProc;
  62. }
  63.  
  64. void    CArrangeList::Dispose()
  65. {
  66.     DisposHandle(itsOrder);
  67.     DisposHandle(itsItems);
  68.     DisposHandle(itemOffsets);
  69.     
  70.     itsPanorama->Dispose();
  71.     itsScrollPane->Dispose();
  72.     
  73.     inherited::Dispose();
  74. }
  75.  
  76. void    CArrangeList::GetIndents(short *theHIndent,short *theVIndent)
  77. {
  78.     *theHIndent = hIndent;
  79.     *theVIndent = vIndent;
  80. }
  81.  
  82. void    CArrangeList::GetRowCount(short *rowCount)
  83. {
  84.     *rowCount = rows;
  85. }
  86.     
  87. void    CArrangeList::GetRowDimensions(short *theWidth,short *theHeight)
  88. {
  89.     *theWidth = rowWidth;
  90.     *theHeight = rowHeight;
  91. }
  92.  
  93. void    CArrangeList::GetSelection(short *theSelection)
  94. {
  95.     *theSelection = currentSelection;
  96. }
  97.  
  98. Boolean    CArrangeList::IsDirty()
  99. {
  100.     return dirty;
  101. }
  102.  
  103. void    CArrangeList::SetIndents(short theHIndent,short theVIndent,
  104.     Boolean redraw)
  105. {
  106.     hIndent = theHIndent;
  107.     vIndent = theVIndent;
  108.     if (redraw)
  109.         Draw();
  110. }
  111.  
  112. void    CArrangeList::SetRowDimensions(short theWidth,short theHeight,
  113.     Boolean redraw)
  114. {
  115.     rowWidth = theWidth;
  116.     rowHeight = theHeight;
  117.     if (redraw)
  118.         Draw();
  119. }
  120.  
  121. void    CArrangeList::SetSelection(short theSelection)
  122. {
  123.     InvertRow(currentSelection);
  124.     currentSelection = theSelection;
  125.     InvertRow(currentSelection);
  126. }
  127.  
  128. void    CArrangeList::SetDirty(Boolean isDirty)
  129. {
  130.     dirty = isDirty;
  131. }
  132.  
  133. void    CArrangeList::SetCompareProc(ShortFunc theFunc)
  134. {
  135.     compareProc = theFunc;
  136. }
  137.  
  138. void    CArrangeList::SetDoubleProc(VoidFunc theFunc)
  139. {
  140.     doubleProc = theFunc;
  141. }
  142.  
  143. void    CArrangeList::AddRow(short count,short rowNum,Boolean redraw)
  144. {
  145.     Size                itemSize;
  146.     register short        i;
  147.     Rect                frameRect;
  148.     
  149.     itemSize = GetHandleSize(itemOffsets);
  150.     SetHandleSize(itemOffsets,itemSize+(long)(count * 4));
  151.     itemSize = GetHandleSize(itsOrder);
  152.     SetHandleSize(itsOrder,itemSize+(long)(count * 4));
  153.     if (ValidRow(rowNum))
  154.     {    BlockMove(&(*itsOrder)[rowNum-1],&(*itsOrder)[rowNum+count-1],
  155.             rows * 4);
  156.     }
  157.     for (i = rows + 1; i < rows+count+1; i ++)
  158.         (*itemOffsets)[i] = (*itemOffsets)[i - 1];
  159.     for (i = 0; i < count; i ++)
  160.         (*itsOrder)[i+rowNum-1] = rows + i;
  161.     rows += count;
  162.     
  163.     itsPanorama->bounds.bottom += count;
  164.     if (redraw)
  165.     {    itsScrollPane->AdjustScrollMax();
  166.         itsPanorama->Prepare();
  167.         frameRect = itsPanorama->frame;
  168.         frameRect.top = rowHeight * (rowNum - 1) + 1;
  169.         EraseRect(&frameRect);
  170.         for (i = rowNum; i <= rows; i ++)
  171.             DrawRow(i);
  172.         InvertRow(currentSelection);
  173.     }
  174.     itsScrollPane->itsEnclosure->Prepare();
  175. }
  176.  
  177. void    CArrangeList::DeleteRow(short count,short rowNum,Boolean redraw)
  178. {
  179.     register short    i,j;
  180.     long            rowOffset,nextOffset,size,totalSize;
  181.     register        theOrder;
  182.     Size            handleSize;
  183.     Rect            frameRect;
  184.     
  185.     for (i = rowNum-1; i < rowNum-1+count; i++)
  186.     {    rowOffset = (*itemOffsets)[(*itsOrder)[i]];
  187.         nextOffset = (*itemOffsets)[(*itsOrder)[i]+1];
  188.         size = nextOffset - rowOffset;
  189.         totalSize = (*itemOffsets)[rows];
  190.         BlockMove(&(*itsItems)[nextOffset],&(*itsItems)[rowOffset],
  191.             totalSize - nextOffset);
  192.         handleSize = GetHandleSize(itsItems);
  193.         SetHandleSize(itsItems,handleSize - size);
  194.         
  195.         BlockMove(&(*itemOffsets)[(*itsOrder)[i]+1],
  196.             &(*itemOffsets)[(*itsOrder)[i]],(rows-(*itsOrder)[i]) * 4);
  197.         for (j = (*itsOrder)[i]; j < rows; j ++)
  198.             (*itemOffsets)[j] -= size;
  199.         handleSize = GetHandleSize(itemOffsets);
  200.         SetHandleSize(itemOffsets,handleSize - 4);
  201.         
  202.         theOrder = (*itsOrder)[i];
  203.         BlockMove(&(*itsOrder)[i+1],&(*itsOrder)[i],(rows - i - 1) * 4);
  204.         for (j = 0; j < rows - 1; j ++)
  205.         {    if ((*itsOrder)[j] > theOrder)
  206.                 (*itsOrder)[j] -= 1;
  207.         }
  208.         handleSize = GetHandleSize(itsOrder);
  209.         SetHandleSize(itsOrder,handleSize - 4);
  210.         rows -= 1;
  211.     }
  212.     itsPanorama->bounds.bottom -= count;
  213.     if (currentSelection > rows)
  214.         currentSelection = rows;
  215.     if (redraw)
  216.     {    itsScrollPane->AdjustScrollMax();
  217.         itsPanorama->Prepare();
  218.         frameRect = itsPanorama->frame;
  219.         frameRect.top = rowHeight * (rowNum - 1) + 1;
  220.         EraseRect(&frameRect);
  221.         for (i = rowNum; i <= rows; i ++)
  222.             DrawRow(i);
  223.         InvertRow(currentSelection);
  224.     }
  225.     itsScrollPane->itsEnclosure->Prepare();
  226. }
  227.  
  228. void    CArrangeList::SetRow(Ptr dataPtr,long dataLen,short rowNum,
  229.     Boolean redraw)
  230. {
  231.     register short        i;
  232.     register LongPtr    offsets;
  233.     long                rowSize;
  234.     register long        delta;
  235.     register long        rowOffset;
  236.     register long        nextOffset;
  237.     Size                itemSize;
  238.     
  239.     if (rowNum > rows)
  240.         return;
  241.     
  242.     offsets = *itemOffsets;
  243.     rowOffset = offsets[rowNum - 1];
  244.     nextOffset = offsets[rowNum];
  245.     rowSize = nextOffset - rowOffset;
  246.     delta = dataLen - rowSize;
  247.     if (delta)
  248.     {    for (i = rowNum; i < rows+1; i ++)
  249.             offsets[i] += delta;
  250.     
  251.         itemSize = GetHandleSize(itsItems);
  252.         SetHandleSize(itsItems,itemSize+delta);
  253.         BlockMove(&(*itsItems)[nextOffset],&(*itsItems)[nextOffset+delta],
  254.             itemSize - nextOffset);
  255.     }
  256.     BlockMove(dataPtr,&(*itsItems)[rowOffset],dataLen);
  257.     if (redraw)
  258.         DrawRow(rowNum);
  259. }
  260.  
  261. void    CArrangeList::DrawRow(register short rowNum)
  262. {
  263.     long    rowSize;
  264.     Ptr        rowPtr;
  265.     
  266.     if (ValidRow(rowNum))
  267.     {    itsPanorama->Prepare();
  268.         MoveTo(hIndent,rowHeight * rowNum - vIndent);
  269.         rowPtr = GetRowOffset(rowNum);
  270.         rowSize = GetRowSize(rowNum);
  271.         
  272.         DrawText(rowPtr,0,rowSize);
  273.     }
  274. }
  275.  
  276. void    CArrangeList::InvertRow(register short rowNum)
  277. {
  278.     Rect    theRect;
  279.     
  280.     if (ValidRow(rowNum))
  281.     {    itsPanorama->Prepare();
  282.         theRect = itsPanorama->frame;
  283.         theRect.top = rowHeight * (rowNum - 1);
  284.         theRect.bottom = rowHeight * rowNum;
  285.         InvertRect(&theRect);
  286.     }
  287. }
  288.  
  289. Boolean    CArrangeList::ValidRow(register short rowNum)
  290. {
  291.     if (rowNum <= rows && rowNum >= 1)
  292.         return true;
  293.     else
  294.         return false;
  295. }
  296.  
  297. void    CArrangeList::Draw()
  298. {
  299.     register short    i;
  300.     Rect            frameRect;
  301.     register short    visTop,visBottom;
  302.     
  303.     itsScrollPane->Prepare();
  304.     frameRect = itsPanorama->frame;
  305.     itsPanorama->FrameToEnclR(&frameRect);
  306.     EraseRect(&frameRect);
  307.     InsetRect(&frameRect,-1,-1);
  308.     FrameRect(&frameRect);
  309.     visTop = itsPanorama->aperture.top / rowHeight + 1;
  310.     visBottom = itsPanorama->aperture.bottom / rowHeight;
  311.     for (i = visTop; i <= visBottom; i ++)
  312.         DrawRow(i);
  313.     InvertRow(currentSelection);
  314.     itsScrollPane->itsEnclosure->Prepare();
  315. }
  316.  
  317. void    CArrangeList::DoClick(Point hitPt,short modifierKeys,long when)
  318. {
  319.     CArrangeTask    *theTask;
  320.     Rect            bounds;
  321.     short            currItem;
  322.     long            hExtent,vExtent;
  323.     
  324.     currItem = hitPt.v / rowHeight + 1;
  325.     if (ValidRow(currItem))
  326.     {    if ((when - clickTime) < GetDblTime())
  327.             (*doubleProc)(this);
  328.         clickTime = when;
  329.         clickRow = currItem;
  330.         theTask = new(CArrangeTask);
  331.         theTask->IArrangeTask(this);
  332.         itsPanorama->Prepare();
  333.         itsPanorama->GetPixelExtent(&hExtent,&vExtent);
  334.         SetRect(&bounds,0,0,(short)hExtent,(short)vExtent);
  335.         
  336.         itsPanorama->TrackMouse(theTask,hitPt,&bounds);
  337.         theTask->Dispose();
  338.     }
  339.     else
  340.     {    InvertRow(currentSelection);
  341.         currentSelection = 0;
  342.     }
  343. }
  344.  
  345. Ptr        CArrangeList::GetRowOffset(register short rowNum)
  346. {
  347.     long    rowOffset;
  348.     
  349.     rowOffset = (*itemOffsets)[(*itsOrder)[rowNum-1]];
  350.     return (Ptr)&(*itsItems)[rowOffset];
  351. }
  352.  
  353. long    CArrangeList::GetRowSize(register short rowNum)
  354. {
  355.     long    rowOffset;
  356.     
  357.     rowOffset = (*itemOffsets)[(*itsOrder)[rowNum-1]];
  358.     return (*itemOffsets)[(*itsOrder)[rowNum-1]+1] - rowOffset;
  359.         
  360. }
  361.  
  362. void    CArrangeList::Sort(short left,short right)
  363. {
  364.     if (left != right)
  365.     {    QuickSort(this,left,right);
  366.         dirty = true;
  367.     }
  368. }
  369.  
  370. Boolean    CArrangeList::Search(register Ptr dataPtr,register short dataLen,
  371.     short *theRow)
  372. {
  373.     register short    i;
  374.     register Ptr    rowOffset;
  375.     register long    rowSize;
  376.     
  377.     for (i = 1; i <= rows; i ++)
  378.     {    rowOffset = GetRowOffset(i);
  379.         rowSize = GetRowSize(i);
  380.         if ((*compareProc)(rowOffset,dataPtr,rowSize,dataLen) >= 0)
  381.         {    *theRow = i;
  382.             return true;
  383.         }
  384.     }
  385.     return false;
  386. }
  387.  
  388. void    QuickSort(CArrangeList *theList,short left,short right)
  389. {
  390.     register short    i,j;
  391.     register Ptr    x;
  392.     register long    length,swap;
  393.     
  394.     i = left;
  395.     j = right;
  396.     
  397.     x = theList->GetRowOffset((left+right)/2+1);
  398.     length = theList->GetRowSize((left+right)/2+1);
  399.     
  400.     do
  401.     {    while ((*theList->compareProc)(theList->GetRowOffset(i+1),x,
  402.                 theList->GetRowSize(i+1),length) < 0 &&
  403.                 i < right)
  404.             i ++;
  405.         while ((*theList->compareProc)(x,theList->GetRowOffset(j+1),length,
  406.                 theList->GetRowSize(j+1)) < 0 &&
  407.                 j > left)
  408.             j --;
  409.         if (i <= j)
  410.         {    swap = (*theList->itsOrder)[i];
  411.             (*theList->itsOrder)[i] = (*theList->itsOrder)[j];
  412.             (*theList->itsOrder)[j] = swap;
  413.             i ++;
  414.             j --;
  415.         }
  416.     }
  417.     while (i <= j);
  418.     
  419.     if (left < j)
  420.         QuickSort(theList,left,j);
  421.     if (i < right)
  422.         QuickSort(theList,i,right);
  423. }
  424.  
  425. short    CompareItems(Ptr aPtr,Ptr bPtr,short aLen,short bLen)
  426. {
  427.     IUMagString(aPtr,bPtr,aLen,bLen);
  428. }
  429.  
  430. void    DoubleClick(CArrangeList *theList)
  431. {
  432.     SysBeep(10);
  433. }
  434.  
  435. void    CArrangeTask::IArrangeTask(CArrangeList *theList)
  436. {
  437.     inherited::IMouseTask(0);
  438.  
  439.     itsList = theList;
  440.     lastItem = theList->currentSelection;
  441.     arranging = false;
  442. }
  443.  
  444. void    CArrangeTask::BeginTracking(Point *startPt)
  445. {
  446.     short    currItem;
  447.     register short        rowHeight;
  448.     
  449.     rowHeight = itsList->rowHeight;
  450.     currItem = startPt->v / rowHeight + 1;
  451.     currItem = Max(currItem,1);
  452.     currItem = Min(currItem,itsList->rows);
  453.     if (lastItem != currItem)
  454.     {    itsList->InvertRow(lastItem);
  455.         itsList->InvertRow(currItem);
  456.         lastItem = currItem;
  457.     }
  458. }
  459.  
  460. void    CArrangeTask::KeepTracking(Point *currPt,Point *prevPt,Point *startPt)
  461. {
  462.     register LongPtr    theOrder;
  463.     register short        currItem,tempItem,i;
  464.     long                swap;
  465.     Rect                theRect;
  466.     short                rowHeight;
  467.     long                vPos;
  468.     short                vSpan;
  469.     
  470.     rowHeight = itsList->rowHeight;
  471.     currItem = currPt->v / rowHeight + 1;
  472.     
  473.     currItem = Max(currItem,1);
  474.     currItem = Min(currItem,itsList->rows);
  475.     
  476.     if (itsList->itsPanorama->AutoScroll(*currPt))
  477.     {    vPos = itsList->itsPanorama->position.v;
  478.         vSpan = itsList->itsPanorama->height /
  479.             itsList->itsPanorama->vScale;
  480.         currItem = Min(currItem,vPos+vSpan);
  481.         currItem = Max(currItem,vPos+1);
  482.     }
  483.     if (currItem != lastItem)
  484.     {    if (!arranging)
  485.         {    SetCursor(*gHandCursor);
  486.             arranging = true;
  487.         }
  488.         itsList->InvertRow(lastItem);
  489.         theOrder = *itsList->itsOrder;
  490.         
  491.         if (currItem < lastItem)
  492.         {    tempItem = lastItem;
  493.             do
  494.             {    tempItem -= 1;
  495.                 swap = theOrder[tempItem-1];
  496.                 theOrder[tempItem-1] = theOrder[tempItem];
  497.                 theOrder[tempItem] = swap;
  498.             }
  499.             while (tempItem != currItem);
  500.         }
  501.         else
  502.         {    tempItem = lastItem;
  503.             do
  504.             {    swap = theOrder[tempItem-1];
  505.                 theOrder[tempItem-1] = theOrder[tempItem];
  506.                 theOrder[tempItem] = swap;
  507.                 tempItem += 1;
  508.             }
  509.             while (tempItem != currItem);
  510.         }
  511.         
  512.         theRect = itsList->itsPanorama->frame;
  513.         if (currItem < lastItem)
  514.         {    theRect.top = rowHeight * (currItem - 1);
  515.             theRect.bottom = rowHeight * lastItem;
  516.             EraseRect(&theRect);
  517.             for (i =  currItem; i <= lastItem; i++)
  518.                 itsList->DrawRow(i);
  519.             itsList->InvertRow(currItem);
  520.         }
  521.         else
  522.         {    theRect.top = rowHeight * (lastItem - 1);
  523.             theRect.bottom = rowHeight * currItem;
  524.             EraseRect(&theRect);
  525.             for (i =  lastItem; i <= currItem; i++)
  526.                 itsList->DrawRow(i);
  527.             itsList->InvertRow(currItem);
  528.         }
  529.         
  530.         lastItem = currItem;
  531.         itsList->dirty = true;
  532.     }
  533. }
  534.  
  535. void    CArrangeTask::EndTracking(Point *currPt,Point *prevPt,Point *startPt)
  536. {
  537.     itsList->currentSelection = lastItem;
  538.     SetCursor(&arrow);
  539. }
  540.  
  541. void    CListPanorama::Draw(Rect *area)
  542. {
  543.     ((CArrangeList *)itsSupervisor)->Draw();
  544. }
  545.  
  546. void    CListPanorama::DoClick(Point hitPt,short modifierKeys,long when)
  547. {
  548.     ((CArrangeList *)itsSupervisor)->DoClick(hitPt,modifierKeys,when);
  549.     itsScrollPane->itsEnclosure->Prepare();
  550. }